from demo.evo.problems import Problem
from eden.evo.aminos import EmptyAmino
from eden.evo.evaluator import Evaluator
from eden.evo.operands import RegisterOperand, ConstOperand
from eden.evo.protein import Protein

ROCK = 1
PAPER = 2
SCISSORS = 3

class RpsAmino(EmptyAmino):
    def __init__(self, left, right, input, output):
        EmptyAmino.__init__(self, left, right)
        self.input = input
        self.output = output
        
    def run(self, context):
        if context.getregister(0) == self.input:
            context.setregister(1, self.output)
        
class PaperForRockAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, ROCK, PAPER)

class RockForRockAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, ROCK, ROCK)

class ScissorsForRockAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, ROCK, SCISSORS)
        
class ScissorsForPaperAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, PAPER, SCISSORS)

class PaperForPaperAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, PAPER, PAPER)
        
class RockForPaperAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, PAPER, ROCK)
        
class RockForScissorsAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, SCISSORS, ROCK)

class ScissorsForScissorsAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, SCISSORS, SCISSORS)

class PaperForScissorsAmino(RpsAmino):
    def __init__(self, left, right):
        RpsAmino.__init__(self, left, right, SCISSORS, PAPER)
        
class RpsEvaluator(Evaluator):
    def evaluate(self, expected, actual):
        if actual[1] == actual[0] % 3 + 1:
            return 1.0
        elif actual[1] == actual[0]:
            return 0.5
        else:
            return 0.0
        
class RpsProblem(Problem):
    def solution(self):
        amino1 = PaperForRockAmino(RegisterOperand(0), ConstOperand(0))
        amino2 = ScissorsForPaperAmino(RegisterOperand(0), ConstOperand(0))
        amino3 = RockForScissorsAmino(RegisterOperand(0), ConstOperand(0))
        return Protein((amino1, amino2, amino3))
    
    def _get_aminos(self):
        return RpsAmino.__subclasses__()
    
    def _get_evaluator(self):
        return RpsEvaluator()
    
    def _test_data(self):
        data = (((ROCK, ), (ROCK, PAPER)),
                ((PAPER, ), (PAPER, SCISSORS)),
                ((SCISSORS, ), (SCISSORS, ROCK)),)
        return data
    
    def _format_solution_equation(self, input, output):
        map = { ROCK : 'ROCK', PAPER : 'PAPER', SCISSORS : 'SCISSORS'}
        equation = '%s --> %s' % (map[input[0]], map[output[1]])
        return equation